#include "realtimecandlestickchart.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QComboBox>
#include <QLabel>
#include <QPushButton>
#include <QDateTime>
#include <QDebug>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QComboBox>
#include <QLabel>
#include <QDateTime>
#include <QDebug>
#include <QtCharts/QBarCategoryAxis>
#include <QValueAxis>
#include <QtCore/QRandomGenerator>
#include <QtCharts/QCandlestickSet>
#include <QtGlobal>
#include <cstdlib>
#include <QtCharts/QLineSeries>
#include <QCheckBox>
#include <QtMath>
#include <QTableWidget>
#include <QTableWidgetItem>
#include <QHeaderView>
#include <QAbstractItemView>
#include <QGuiApplication>
#include <QScreen>
#include <QGraphicsLineItem>
#include <QGraphicsRectItem>
#include <QGraphicsSimpleTextItem>
#include <QFontMetrics>

RealTimeCandlestickChart::RealTimeCandlestickChart(QWidget *parent)
    : QWidget(parent)
    , m_client(new BinanceKLineClient(this))
    , m_chart(new QChart())
    , m_series(new QCandlestickSeries())
    , m_chartView(new QChartView(m_chart))
    , m_zoomFactor(1.0)
    , m_candleWidth(0.6)
    , m_isPanning(false)
    , m_lastPanPoint(QPoint())
    , m_visibleBars(100)
    , m_isRealTime(false)
    , m_startIndex(0)
    , m_minPrice(0.0)
    , m_maxPrice(0.0)
    , m_smaSeries(nullptr)
    , m_emaSeries(nullptr)
    , m_upperBBSeries(nullptr)
    , m_lowerBBSeries(nullptr)
    , m_macdSeries(nullptr)
    , m_macdSignalSeries(nullptr)
    , m_rsiSeries(nullptr)
    , m_rsiAxis(nullptr)
    , m_chkSMA(nullptr)
    , m_chkEMA(nullptr)
    , m_chkBB(nullptr)
    , m_chkRSI(nullptr)
    , m_chkMACD(nullptr)
{
    setupUI();
    initializeSymbols();
    setupChart();
    setupZoomAndDrag();
    setupConnections();


}

RealTimeCandlestickChart::~RealTimeCandlestickChart()
{
    stopRealTimeData();
}

void RealTimeCandlestickChart::setupUI()
{
    QVBoxLayout *mainLayout = new QVBoxLayout(this);

    // 第一行控制栏
    QHBoxLayout *controlLayout1 = new QHBoxLayout();
    QLabel*label_mark=new QLabel("交易对:");
    label_mark->setStyleSheet("QLabel{background:none;color:gray;font-weight:bold;}");
    controlLayout1->addWidget(label_mark);
    m_symbolCombo = new QComboBox();
    m_symbolCombo->setFixedWidth(90);
    //m_symbolCombo->setMinimumWidth(80);
    m_symbolCombo->setStyleSheet(
            "QComboBox {"
            "color:white;"\
            "background-color: gray;" // 背景颜色
            "border: 1px solid #d3d3d3;"  // 边框
            "border-radius: 5px;"         // 边框圆角
            "padding: 5px;"               // 内边距
            "selection-background-color: #c0c0c0;" // 选中项背景色
            "}"
            "QComboBox::drop-down {"
            "subcontrol-origin: padding;"
            "subcontrol-position: top right;"
            "width: 12px;" // 下拉按钮的宽度
            "background-color:green;"\
            "color:green;"\
            "}"
            "QComboBox QAbstractItemView {" // 下拉列表项的样式
            "selection-background-color: #e0e0e0;" // 选中项背景色
            "background: #ffffff;" // 下拉列表背景色
            "}"
            );

    controlLayout1->addWidget(m_symbolCombo);

    QLabel*time_period=new QLabel("时间周期:");
    time_period->setStyleSheet("QLabel{background:none;color:gray;font-weight:bold;}");
    controlLayout1->addWidget(time_period);

    m_intervalCombo = new QComboBox();
    m_intervalCombo->setFixedWidth(90);
    m_intervalCombo->setStyleSheet(
        "QComboBox {"
        "color:white;"\
        "background-color: gray;" // 背景颜色
        "border: 1px solid #d3d3d3;"  // 边框
        "border-radius: 5px;"         // 边框圆角
        "padding: 5px;"               // 内边距
        "selection-background-color: #c0c0c0;" // 选中项背景色
        "}"
        "QComboBox::drop-down {"
        "subcontrol-origin: padding;"
        "subcontrol-position: top right;"
        "width: 12px;" // 下拉按钮的宽度
        "background-color:green;"\
        "color:green;"\
        "}"
        "QComboBox QAbstractItemView {" // 下拉列表项的样式
        "selection-background-color: #e0e0e0;" // 选中项背景色
        "background: #ffffff;" // 下拉列表背景色
        "}"
        );


    m_intervalCombo->addItems({"1m", "3m", "5m", "15m", "30m", "1h", "4h", "1d"});
    controlLayout1->addWidget(m_intervalCombo);





    m_statusLabel = new QLabel("状态: 未连接");
    m_statusLabel->setStyleSheet("QLabel{background:none;color:gray;font-weight:bold;}");

    controlLayout1->addWidget(m_statusLabel);

    m_connectBtn = new QPushButton("开始");
    m_connectBtn->setMinimumWidth(90);
    m_connectBtn->setStyleSheet("QPushButton { \
    color: white;\
                          border: none;\
                          width: 30px;\
                          height: 30px;\
                            background-color:gray;\
                          border-radius: 4px;\
                          }\
                          QPushButton:hover {\
                          background-color: #555555;\
                          }");\
    m_disconnectBtn = new QPushButton("停止");
    m_disconnectBtn->setMinimumWidth(90);
    m_disconnectBtn->setStyleSheet("QPushButton { \
                            color:white;\
                          border: none;\
                          width: 30px;\
                          height: 30px;\
                              background-color:gray;\
                          border-radius: 4px;\
                          }\
                          QPushButton:hover {\
                            color:red;\
                          background-color: #555555;\
                          }");\
    m_disconnectBtn->setEnabled(false);


    m_resetZoomBtn = new QPushButton("重置");
    m_resetZoomBtn->setFixedWidth(90);
    //m_resetZoomBtn->setFixedSize(50, 25);
    m_resetZoomBtn->setToolTip("重置缩放和位置");
    m_resetZoomBtn->setStyleSheet("QPushButton { \
    color: white;\
                          border: none;\
                          width: 30px;\
                          height: 30px;\
                            background-color:gray;\
                          border-radius: 4px;\
                          }\
                          QPushButton:hover {\
                          background-color: #555555;\
                          }");

    controlLayout1->addWidget(m_connectBtn);
    controlLayout1->addWidget(m_disconnectBtn);
     controlLayout1->addWidget(m_resetZoomBtn);




    m_priceLabel = new QLabel("最新价格: -");
    m_priceLabel->setStyleSheet("background:none;font-weight: bold; font-size: 12px;color:gray;");
    controlLayout1->addWidget(m_priceLabel);

    m_dataCountLabel = new QLabel("数据: 0");
    m_dataCountLabel->setStyleSheet("background:none;color: blue;");
    controlLayout1->addWidget(m_dataCountLabel);





    // 第二行缩放控制栏
    //QHBoxLayout *controlLayout2 = new QHBoxLayout();
    QLabel*scale=new QLabel("缩放:");
    scale->setStyleSheet("QLabel{background:none;color:gray;font-weight:bold;}");
    controlLayout1->addWidget(scale);

    m_zoomOutBtn = new QPushButton("─");
    m_zoomOutBtn->setStyleSheet("QPushButton { \
    color:white;\
                          border: none;\
                          width: 30px;\
                          height: 30px;\
                          color:gray;\
                          border-radius: 4px;\
                            background:none;\
                          }\
                          QPushButton:hover {\
                          background-color: #555555;\
                          }");\
        m_zoomOutBtn->setFixedSize(30, 25);

    m_zoomOutBtn->setToolTip("缩小");

    m_zoomSlider = new QSlider(Qt::Horizontal);
    m_zoomSlider->setRange(10, 200);
    m_zoomSlider->setValue(100);
    m_zoomSlider->setFixedWidth(150);
    m_zoomSlider->setToolTip("缩放调节");
    m_zoomSlider->setStyleSheet("background:none;");
    m_zoomSlider->setStyleSheet("QSlider{background:none;}"
                                "QSlider::groove:horizontal {\
    height: 2px;\
    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #B1B1B1, stop:1 #c4c4c4);\
    border-radius: 2px;\
    margin: 2px 0;\
}\
QSlider::handle:horizontal {\
    background: QLinearGradient(cx:0, cy:0, radius:1, fx:0.5, fy:0.5, stop:0 red, stop:1 green);\
    width: 5px;\
    height: 3px;\
    margin: -5px 3px -5px 6px;\
    border-radius: 2px;\
    border: 2px solid #ffffff;\
}\
\
QSlider::sub-page:horizontal {\
    height:2px;\
    background: rgba(80,166,234,1);\
    border-radius: 6px;\
}\
");


    m_zoomInBtn = new QPushButton("┼");
    m_zoomInBtn->setFixedSize(30, 25);
    m_zoomInBtn->setToolTip("放大");

    m_zoomInBtn->setStyleSheet("QPushButton { \
    color:white;\
                          border: none;\
                          width: 30px;\
                          height: 30px;\
                        color:gray;\
                           background:none;\
                          border-radius: 4px;\
                          }\
                          QPushButton:hover {\
                          background-color: #555555;\
                          }");\




    m_zoomLabel = new QLabel("缩放: 100%");
    m_zoomLabel->setStyleSheet("background:none;color: blue; font-size: 11px;");

    controlLayout1->addWidget(m_zoomOutBtn);
    controlLayout1->addWidget(m_zoomSlider);
    controlLayout1->addWidget(m_zoomInBtn);
    controlLayout1->addWidget(m_zoomLabel);

    //controlLayout1->addStretch();


    // 指标开关
    m_chkSMA = new QCheckBox("SMA");
    m_chkEMA = new QCheckBox("EMA");
    m_chkBB = new QCheckBox("BOLL");
    m_chkRSI = new QCheckBox("RSI");
    m_chkMACD = new QCheckBox("MACD");
    m_chkSMA->setToolTip("简单移动平均线");
    m_chkEMA->setToolTip("指数移动平均线");
    m_chkBB->setToolTip("布林带");
    m_chkRSI->setToolTip("相对强弱指数");
    m_chkMACD->setToolTip("MACD 指标");
    controlLayout1->addWidget(m_chkSMA);
    controlLayout1->addWidget(m_chkEMA);
    controlLayout1->addWidget(m_chkBB);
    controlLayout1->addWidget(m_chkRSI);
    controlLayout1->addWidget(m_chkMACD);



    // 提示标签
    QLabel *hintLabel = new QLabel("提示: 鼠标滚轮缩放 | 右键拖拽平移 | Ctrl+滚轮调整蜡烛宽度");
    hintLabel->setStyleSheet("color: gray; font-size: 10px;background:none;");
    controlLayout1->addWidget(hintLabel);
    controlLayout1->setContentsMargins(0,0,0,10);


    mainLayout->addLayout(controlLayout1);


    // 图表区域
    m_chartView->setRenderHint(QPainter::Antialiasing);
    // 限制最小尺寸为合理值并使用屏幕可用区域做约束，避免窗口最小尺寸超过显示器分辨率导致 setGeometry 失败
    QRect avail = QGuiApplication::primaryScreen() ? QGuiApplication::primaryScreen()->availableGeometry() : QRect(0,0,1920,1080);
    int minW = qMin(800, avail.width() - 200);
    int minH = qMin(700, avail.height() - 120);
    if (minW < 200) minW = 200;
    if (minH < 200) minH = 200;
    m_chartView->setMinimumSize(minW, minH);
    mainLayout->addWidget(m_chartView);
   // mainLayout->setSpacing(5);
    mainLayout->setContentsMargins(0,25,0,0);

}

void RealTimeCandlestickChart::initializeSymbols()
{
    m_symbolMap["BTC/USDT"] = "btcusdt";
    m_symbolMap["ETH/USDT"] = "ethusdt";
    m_symbolMap["BNB/USDT"] = "bnbusdt";
    m_symbolMap["ADA/USDT"] = "adausdt";
    m_symbolMap["DOT/USDT"] = "dotusdt";
    m_symbolMap["LINK/USDT"] = "linkusdt";
    m_symbolMap["LTC/USDT"] = "ltcusdt";
    m_symbolMap["BCH/USDT"] = "bchusdt";
    m_symbolMap["XRP/USDT"] = "xrpusdt";
    m_symbolMap["SOL/USDT"] = "solusdt";

    m_symbolCombo->clear();
    for (auto it = m_symbolMap.begin(); it != m_symbolMap.end(); ++it) {
        m_symbolCombo->addItem(it.key());
    }
}

void RealTimeCandlestickChart::setupChart()
{
    // 设置K线系列
    m_series->setName("实时K线");
    m_series->setIncreasingColor(QColor(0, 255, 0));    // 阳线绿色
    m_series->setDecreasingColor(QColor(255, 0, 0));    // 阴线红色

    m_series->setBodyOutlineVisible(true);
    m_series->setCapsVisible(true);
    m_series->setCapsWidth(0.8);
    m_series->setBodyWidth(m_candleWidth);

    m_chart->addSeries(m_series);
    m_chart->setTitle("Binance实时K线图 - 等待连接...");
    m_chart->setAnimationOptions(QChart::SeriesAnimations);
    m_chart->setTheme(QChart::ChartThemeDark);

    // 创建坐标轴
    QBarCategoryAxis *axisX = new QBarCategoryAxis();
    axisX->setTitleText("时间");
    axisX->setLabelsAngle(-90);

    QValueAxis *axisY = new QValueAxis();
    axisY->setTitleText("价格 (USDT)");
    axisY->setLabelFormat("%.2f");

    m_chart->addAxis(axisX, Qt::AlignBottom);
    m_chart->addAxis(axisY, Qt::AlignLeft);

    m_series->attachAxis(axisX);
    m_series->attachAxis(axisY);

    // 创建用于 RSI 的右侧轴（0-100）
    m_rsiAxis = new QValueAxis();
    m_rsiAxis->setRange(0, 100);
    m_rsiAxis->setTitleText("RSI");
    m_rsiAxis->setLabelFormat("%d");
    m_chart->addAxis(m_rsiAxis, Qt::AlignRight);

    // 创建指标系列（默认不显示），并绑定到价格轴
    m_smaSeries = new QLineSeries(); m_smaSeries->setName("SMA");
    m_emaSeries = new QLineSeries(); m_emaSeries->setName("EMA");
    m_upperBBSeries = new QLineSeries(); m_upperBBSeries->setName("BOLL_UP");
    m_lowerBBSeries = new QLineSeries(); m_lowerBBSeries->setName("BOLL_LOW");
    m_macdSeries = new QLineSeries(); m_macdSeries->setName("MACD");
    m_macdSignalSeries = new QLineSeries(); m_macdSignalSeries->setName("MACD_SIG");
    m_rsiSeries = new QLineSeries(); m_rsiSeries->setName("RSI");

    m_chart->addSeries(m_smaSeries);
    m_chart->addSeries(m_emaSeries);
    m_chart->addSeries(m_upperBBSeries);
    m_chart->addSeries(m_lowerBBSeries);
    m_chart->addSeries(m_macdSeries);
    m_chart->addSeries(m_macdSignalSeries);
    m_chart->addSeries(m_rsiSeries);

    // attach to axes
    m_smaSeries->attachAxis(axisX); m_smaSeries->attachAxis(axisY);
    m_emaSeries->attachAxis(axisX); m_emaSeries->attachAxis(axisY);
    m_upperBBSeries->attachAxis(axisX); m_upperBBSeries->attachAxis(axisY);
    m_lowerBBSeries->attachAxis(axisX); m_lowerBBSeries->attachAxis(axisY);
    m_macdSeries->attachAxis(axisX); m_macdSeries->attachAxis(axisY);
    m_macdSignalSeries->attachAxis(axisX); m_macdSignalSeries->attachAxis(axisY);
    m_rsiSeries->attachAxis(axisX); m_rsiSeries->attachAxis(m_rsiAxis);

    m_chart->legend()->setVisible(true);
    m_chart->legend()->setAlignment(Qt::AlignBottom);

    // 初始化悬停用的十字线与信息浮层（添加到 chart 的 scene）
    if (QGraphicsScene *scene = m_chart->scene()) {
        m_vLine = scene->addLine(0,0,0,0, QPen(QColor(180,180,180,200), 1, Qt::DashLine));
        m_hLine = scene->addLine(0,0,0,0, QPen(QColor(180,180,180,200), 1, Qt::DashLine));
        m_vLine->setVisible(false);
        m_hLine->setVisible(false);

        m_infoBox = scene->addRect(0,0,120,64, QPen(Qt::NoPen), QBrush(QColor(30,30,30,220)));
        m_infoBox->setZValue(10);
        m_infoBox->setVisible(false);

        m_infoText = scene->addSimpleText(QString());
        QFont f = m_infoText->font(); f.setPointSize(9); m_infoText->setFont(f);
        m_infoText->setBrush(QBrush(Qt::white));
        m_infoText->setZValue(11);
        m_infoText->setVisible(false);
    }
}

void RealTimeCandlestickChart::setupZoomAndDrag()
{
    // 启用矩形缩放
    m_chartView->setRubberBand(QChartView::RectangleRubberBand);

    // 安装事件过滤器
    m_chartView->viewport()->installEventFilter(this);
    m_chartView->setMouseTracking(true);

    // 启用捏合手势
    m_chartView->grabGesture(Qt::PinchGesture);
}

void RealTimeCandlestickChart::setupConnections()
{
    // Binance客户端信号
    connect(m_client, &BinanceKLineClient::kLineDataReceived,
            this, &RealTimeCandlestickChart::onKLineDataReceived);
    connect(m_client, &BinanceKLineClient::kLineUpdated,
            this, &RealTimeCandlestickChart::onKLineUpdated);
    connect(m_client, &BinanceKLineClient::historicalDataReceived,
            this, &RealTimeCandlestickChart::onHistoricalDataReceived);
    connect(m_client, &BinanceKLineClient::connected,
            this, &RealTimeCandlestickChart::onConnected);
    connect(m_client, &BinanceKLineClient::disconnected,
            this, &RealTimeCandlestickChart::onDisconnected);
    connect(m_client, &BinanceKLineClient::errorOccurred,
            this, &RealTimeCandlestickChart::onErrorOccurred);

    // UI控件信号
    connect(m_symbolCombo, &QComboBox::currentTextChanged,
            this, &RealTimeCandlestickChart::onSymbolChanged);
    connect(m_intervalCombo, &QComboBox::currentTextChanged,
            this, &RealTimeCandlestickChart::onIntervalChanged);
    connect(m_connectBtn, &QPushButton::clicked,
            this, &RealTimeCandlestickChart::onConnectClicked);
    connect(m_disconnectBtn, &QPushButton::clicked,
            this, &RealTimeCandlestickChart::onDisconnectClicked);

    // 缩放控制信号
    connect(m_zoomInBtn, &QPushButton::clicked,
            this, &RealTimeCandlestickChart::onZoomIn);
    connect(m_zoomOutBtn, &QPushButton::clicked,
            this, &RealTimeCandlestickChart::onZoomOut);
    connect(m_resetZoomBtn, &QPushButton::clicked,
            this, &RealTimeCandlestickChart::onResetZoom);
    connect(m_zoomSlider, &QSlider::valueChanged,
            this, &RealTimeCandlestickChart::onZoomSliderChanged);

    // 指标开关
    connect(m_chkSMA, &QCheckBox::toggled, this, &RealTimeCandlestickChart::onIndicatorToggled);
    connect(m_chkEMA, &QCheckBox::toggled, this, &RealTimeCandlestickChart::onIndicatorToggled);
    connect(m_chkBB, &QCheckBox::toggled, this, &RealTimeCandlestickChart::onIndicatorToggled);
    connect(m_chkRSI, &QCheckBox::toggled, this, &RealTimeCandlestickChart::onIndicatorToggled);
    connect(m_chkMACD, &QCheckBox::toggled, this, &RealTimeCandlestickChart::onIndicatorToggled);
}

// 缩放控制实现
void RealTimeCandlestickChart::onZoomIn()
{
    m_zoomFactor *= 1.2;
    if (m_zoomFactor > 5.0) m_zoomFactor = 5.0;
    updateZoom();
}

void RealTimeCandlestickChart::onZoomOut()
{
    m_zoomFactor /= 1.2;
    if (m_zoomFactor < 0.2) m_zoomFactor = 0.2;
    updateZoom();
}

void RealTimeCandlestickChart::onResetZoom()
{
    m_zoomFactor = 1.0;
    m_candleWidth = 0.6;
    updateZoom();

    // 重置图表显示范围
    calculatePriceRange();
    if (QValueAxis *axisY = qobject_cast<QValueAxis*>(m_chart->axisY())) {
        double margin = (m_maxPrice - m_minPrice) * 0.1;
        axisY->setRange(m_minPrice - margin, m_maxPrice + margin);
    }
}

void RealTimeCandlestickChart::onZoomSliderChanged(int value)
{
    m_zoomFactor = value / 100.0;
    updateZoom();
}

void RealTimeCandlestickChart::updateZoom()
{
    // 更新蜡烛宽度
    double newCandleWidth = 0.6 * m_zoomFactor;
    newCandleWidth = qMax(0.1, qMin(2.0, newCandleWidth));
    m_series->setBodyWidth(newCandleWidth);

    // 更新可见K线数量
    m_visibleBars = static_cast<int>(100 / m_zoomFactor);
    m_visibleBars = qMax(20, qMin(500, m_visibleBars));

    // 更新缩放标签和滑块
    m_zoomLabel->setText(QString("缩放: %1%").arg(static_cast<int>(m_zoomFactor * 100)));
    m_zoomSlider->blockSignals(true);
    m_zoomSlider->setValue(static_cast<int>(m_zoomFactor * 100));
    m_zoomSlider->blockSignals(false);

    // 更新图表显示范围
    updateChartRange();
}

void RealTimeCandlestickChart::updateChartRange()
{
    if (m_klineData.isEmpty()) return;

    // 计算显示范围
    int startIndex = qMax(0, m_klineData.size() - m_visibleBars);
    int endIndex = m_klineData.size() - 1;

    // 更新X轴范围
    if (QBarCategoryAxis *axisX = qobject_cast<QBarCategoryAxis*>(m_chart->axisX())) {
        QStringList visibleCategories;
        for (int i = startIndex; i <= endIndex; ++i) {
            if (i < m_categories.size()) {
                visibleCategories << m_categories[i];
            }
        }
        axisX->clear();
        axisX->append(visibleCategories);
    }

    // 更新数据计数
    m_dataCountLabel->setText(QString("数据: %1").arg(m_klineData.size()));
}

// 事件处理
bool RealTimeCandlestickChart::eventFilter(QObject *obj, QEvent *event)
{
    if (obj == m_chartView->viewport()) {
            if (event->type() == QEvent::Gesture) {
            QGestureEvent *gestureEvent = static_cast<QGestureEvent*>(event);
            if (QGesture *pinch = gestureEvent->gesture(Qt::PinchGesture)) {
                pinchTriggered(static_cast<QPinchGesture*>(pinch));
                return true;
            }
            } else if (event->type() == QEvent::MouseButtonPress) {
                // 点击事件：将点击对应的K线信息显示到表格中（在表内），并选中表格，避免外部弹出
                QMouseEvent *me = static_cast<QMouseEvent*>(event);
                QPoint pos = me->pos();
                QRect vp = m_chartView->viewport()->rect();
                if (vp.contains(pos) && !m_klineData.isEmpty()) {
                    int w = qMax(1, vp.width());
                    double ratio = pos.x() / static_cast<double>(w);
                    ratio = qBound(0.0, ratio, 1.0);
                    int idx = m_startIndex + static_cast<int>(ratio * qMax(1, m_visibleBars - 1) + 0.5);
                    idx = qBound(0, idx, m_klineData.size() - 1);
                    updateHoverInfo(idx);
                }
                return false;
            } else if (event->type() == QEvent::MouseMove) {
            // 悬停显示K线信息
            QMouseEvent *me = static_cast<QMouseEvent*>(event);
            QPoint pos = me->pos();
            QRect vp = m_chartView->viewport()->rect();
            if (!vp.contains(pos)) {
                clearHoverInfo();
                return false;
            }
            if (m_klineData.isEmpty()) {
                clearHoverInfo();
                return false;
            }
            int w = qMax(1, vp.width());
            double ratio = pos.x() / static_cast<double>(w);
            ratio = qBound(0.0, ratio, 1.0);
            int idx = m_startIndex + static_cast<int>(ratio * qMax(1, m_visibleBars - 1) + 0.5);
            idx = qBound(0, idx, m_klineData.size() - 1);
            updateHoverInfo(idx);
            return false;
        } else if (event->type() == QEvent::Leave) {
            clearHoverInfo();
        }
    }
    return QWidget::eventFilter(obj, event);
}

void RealTimeCandlestickChart::pinchTriggered(QPinchGesture *gesture)
{
    QPinchGesture::ChangeFlags changeFlags = gesture->changeFlags();

    if (changeFlags & QPinchGesture::ScaleFactorChanged) {
        double scaleFactor = gesture->scaleFactor();

        if (scaleFactor > 1.0) {
            onZoomIn();
        } else if (scaleFactor < 1.0) {
            onZoomOut();
        }
    }
}

void RealTimeCandlestickChart::wheelEvent(QWheelEvent *event)
{
    if (event->modifiers() & Qt::ControlModifier) {
        // Ctrl + 滚轮调整蜡烛宽度
        double factor = event->angleDelta().y() > 0 ? 1.1 : 0.9;
        adjustCandleWidth(factor);
        event->accept();
    } else {
        // 普通滚轮缩放
        if (event->angleDelta().y() > 0) {
            onZoomIn();
        } else {
            onZoomOut();
        }
        event->accept();
    }
}

void RealTimeCandlestickChart::adjustCandleWidth(double factor)
{
    m_candleWidth *= factor;
    m_candleWidth = qMax(0.1, qMin(2.0, m_candleWidth));
    m_series->setBodyWidth(m_candleWidth);
}

void RealTimeCandlestickChart::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::RightButton) {
        m_isPanning = true;
        m_lastPanPoint = event->pos();
        m_chartView->setCursor(Qt::ClosedHandCursor);
        event->accept();
    } else {
        QWidget::mousePressEvent(event);
    }
}

void RealTimeCandlestickChart::mouseMoveEvent(QMouseEvent *event)
{
    if (m_isPanning) {
        QPoint delta = event->pos() - m_lastPanPoint;
        m_lastPanPoint = event->pos();
        panChart(delta);
        event->accept();
    } else {
        QWidget::mouseMoveEvent(event);
    }
}

void RealTimeCandlestickChart::mouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == Qt::RightButton && m_isPanning) {
        m_isPanning = false;
        m_chartView->setCursor(Qt::ArrowCursor);
        event->accept();
    } else {
        QWidget::mouseReleaseEvent(event);
    }
}

void RealTimeCandlestickChart::panChart(const QPoint &delta)
{
    if (QValueAxis *axisY = qobject_cast<QValueAxis*>(m_chart->axisY())) {
        double range = axisY->max() - axisY->min();
        double panFactor = range / m_chartView->height();
        
        // 计算平移量
        double shift = -delta.y() * panFactor;
        
        // 计算新的范围，保持区间大小不变
        double newMin = axisY->min() + shift;
        double newMax = axisY->max() + shift;
        
        // 添加 10% 的边距
        double margin = range * 0.1;
        
        // 如果超出数据范围，则限制在合理范围内
        if (newMin < m_minPrice - margin) {
            newMin = m_minPrice - margin;
            newMax = newMin + range;  // 保持区间大小不变
        } else if (newMax > m_maxPrice + margin) {
            newMax = m_maxPrice + margin;
            newMin = newMax - range;  // 保持区间大小不变
        }
        
        // 确保最大值始终大于最小值
        if (newMax > newMin) {
            axisY->setRange(newMin, newMax);
        }
    }
}

// 数据管理
void RealTimeCandlestickChart::calculatePriceRange()
{
    if (m_klineData.isEmpty()) return;

    m_minPrice = m_klineData.first().low;
    m_maxPrice = m_klineData.first().high;

    for (const KLineData &data : m_klineData) {
        m_minPrice = qMin(m_minPrice, data.low);
        m_maxPrice = qMax(m_maxPrice, data.high);
    }

    // 包括当前正在形成的K线
    if (m_currentKLine.timestamp > 0) {
        m_minPrice = qMin(m_minPrice, m_currentKLine.low);
        m_maxPrice = qMax(m_maxPrice, m_currentKLine.high);
    }
}

void RealTimeCandlestickChart::startRealTimeData(const QString& symbol, const QString& interval)
{
    m_isRealTime = true;
    m_client->connectToBinance(symbol, interval);
    m_client->fetchHistoricalData(symbol, interval, 100);//默认值100
}

void RealTimeCandlestickChart::stopRealTimeData()
{
    m_isRealTime = false;
    m_client->disconnectFromBinance();
}

void RealTimeCandlestickChart::restartRealTimeData()
{
    stopRealTimeData();
    QTimer::singleShot(200, this, [this]() {
        QString symbol = m_symbolCombo->currentText();
        QString apiSymbol = m_symbolMap.value(symbol, symbol.toLower());
        QString interval = m_intervalCombo->currentText();
        startRealTimeData(apiSymbol, interval);
    });
}

void RealTimeCandlestickChart::onSymbolChanged()
{
    QString symbol = m_symbolCombo->currentText();
    m_chart->setTitle(QString("%1 - K线图").arg(symbol));

    if (m_isRealTime) {
        m_statusLabel->setText("状态: 切换交易对中...");
        restartRealTimeData();
    }
}

void RealTimeCandlestickChart::onIntervalChanged()
{
    QString interval = m_intervalCombo->currentText();
    QString symbol = m_symbolCombo->currentText();
    m_chart->setTitle(QString("%1 %2 - K线图").arg(symbol).arg(interval));

    if (m_isRealTime) {
        m_statusLabel->setText("状态: 切换时间周期中...");
        restartRealTimeData();
    }
}

void RealTimeCandlestickChart::onConnectClicked()
{
    QString symbol = m_symbolCombo->currentText();
    QString apiSymbol = m_symbolMap.value(symbol, symbol.toLower());
    QString interval = m_intervalCombo->currentText();
    startRealTimeData(apiSymbol, interval);
}

void RealTimeCandlestickChart::onDisconnectClicked()
{
    stopRealTimeData();
}

// Binance数据回调
void RealTimeCandlestickChart::onKLineDataReceived(const KLineData& data)
{
    addKLineToChart(data);

    QString changePercent = QString("%1%2%")
                                .arg(data.close >= data.open ? "+" : "")
                                .arg(((data.close - data.open) / data.open * 100), 0, 'f', 2);

    m_chart->setTitle(QString("%1 %2 - 最新: %3 (%4)")
                          .arg(data.symbol.toUpper())
                          .arg(m_intervalCombo->currentText())
                          .arg(data.close, 0, 'f', 2)
                          .arg(changePercent));
}

void RealTimeCandlestickChart::onKLineUpdated(const KLineData& data)
{
    updateKLineInChart(data);
    updateLatestKLine(data);

    QString priceText = QString("最新: %1").arg(data.close, 0, 'f', 2);
    if (data.close >= data.open) {
        m_priceLabel->setStyleSheet("background:none;font-weight: bold; color: green; font-size: 12px;");
        priceText += " ▲";
    } else {
        m_priceLabel->setStyleSheet("background:none;font-weight: bold; color: red; font-size: 12px;");
        priceText += " ▼";
    }
    m_priceLabel->setText(priceText);
}

void RealTimeCandlestickChart::onHistoricalDataReceived(const QVector<KLineData>& data)
{
    m_series->clear();
    m_klineData = data;
    m_categories.clear();

    if (data.isEmpty()) return;

    // 添加历史数据到图表
    for (int i = 0; i < data.size(); ++i) {
        const KLineData& kline = data[i];
        addKLineToChart(kline);
    }

    calculatePriceRange();
    updateChartRange();

    qDebug() << "历史数据加载完成:" << data.size() << "根K线";
}

void RealTimeCandlestickChart::addKLineToChart(const KLineData& data)
{
    // 检查是否已存在相同时间戳的K线
    for (int i = 0; i < m_series->count(); ++i) {
        QCandlestickSet *set = m_series->sets().at(i);
        if (set->timestamp() == data.timestamp) {
            // 更新现有K线
            set->setOpen(data.open);
            set->setHigh(data.high);
            set->setLow(data.low);
            set->setClose(data.close);
            return;
        }
    }

    // 添加新K线
    QCandlestickSet *candleSet = new QCandlestickSet(data.timestamp);
    candleSet->setOpen(data.open);
    candleSet->setHigh(data.high);
    candleSet->setLow(data.low);
    candleSet->setClose(data.close);

    m_series->append(candleSet);
    m_klineData.append(data);

    // 更新X轴标签
    QDateTime dt = QDateTime::fromMSecsSinceEpoch(data.timestamp);
   // m_categories << dt.toString("MM-dd\nhh:mm");
    m_categories << dt.toString("hh:mm");
    if (QBarCategoryAxis *axisX = qobject_cast<QBarCategoryAxis*>(m_chart->axisX())) {
        axisX->append(m_categories.last());
    }

    // 限制数据量
    if (m_series->count() > 500) {
        // 移除最早一根K线及对应类别
        m_series->remove(m_series->sets().first());
        m_klineData.removeFirst();
        if (!m_categories.isEmpty()) {
            QString removedCategory = m_categories.takeFirst();
            if (QBarCategoryAxis *axisX = qobject_cast<QBarCategoryAxis*>(m_chart->axisX())) {
                axisX->remove(removedCategory);
            }
        }
        // 当删除最早数据时，startIndex 需要向前移动以保持视窗一致
        m_startIndex = qMax(0, m_startIndex - 1);
    }

    updateChartRange();
    // 更新指标
    calculateIndicators();
}

void RealTimeCandlestickChart::updateKLineInChart(const KLineData& data)
{
    // 更新当前正在形成的K线
    for (int i = 0; i < m_series->count(); ++i) {
        QCandlestickSet *set = m_series->sets().at(i);
        if (set->timestamp() == data.timestamp) {
            set->setOpen(data.open);
            set->setHigh(data.high);
            set->setLow(data.low);
            set->setClose(data.close);
            break;
        }
    }

    // 更新指标（最新K线变化）
    calculateIndicators();

}
void RealTimeCandlestickChart::updateLatestKLine(const KLineData& data)
{
    m_currentKLine = data;
}

void RealTimeCandlestickChart::onConnected()
{
    m_statusLabel->setText("状态: 已连接");
    m_statusLabel->setStyleSheet("background:none;color: green;");
    m_connectBtn->setEnabled(false);
    m_disconnectBtn->setEnabled(true);
}

void RealTimeCandlestickChart::onDisconnected()
{
    m_statusLabel->setText("状态: 未连接");
    m_statusLabel->setStyleSheet("color: gray;");
    m_connectBtn->setEnabled(true);
    m_disconnectBtn->setEnabled(false);
}

void RealTimeCandlestickChart::onErrorOccurred(const QString& error)
{
    m_statusLabel->setText("状态: 错误");
    m_statusLabel->setStyleSheet("color: red;");
    qDebug() << "错误:" << error;
}

// ---------------- 指标计算与渲染 ----------------
void RealTimeCandlestickChart::onIndicatorToggled(bool /*checked*/)
{
    // 简单响应：根据当前 checkbox 状态刷新可见性
    toggleIndicatorSeries(m_smaSeries, m_chkSMA->isChecked());
    toggleIndicatorSeries(m_emaSeries, m_chkEMA->isChecked());
    toggleIndicatorSeries(m_upperBBSeries, m_chkBB->isChecked());
    toggleIndicatorSeries(m_lowerBBSeries, m_chkBB->isChecked());
    toggleIndicatorSeries(m_macdSeries, m_chkMACD->isChecked());
    toggleIndicatorSeries(m_macdSignalSeries, m_chkMACD->isChecked());
    toggleIndicatorSeries(m_rsiSeries, m_chkRSI->isChecked(), m_rsiAxis);
    // 立刻刷新可见部分
    refreshIndicatorSeries();
}

void RealTimeCandlestickChart::toggleIndicatorSeries(QLineSeries *series, bool visible, QAbstractAxis *axis)
{
    if (!series) return;
    series->setVisible(visible);
    if (axis) axis->setVisible(visible);
}

void RealTimeCandlestickChart::calculateIndicators()
{
    int n = m_klineData.size();
    if (n == 0) {
        m_smaValues.clear(); m_emaValues.clear(); m_upperBBValues.clear(); m_lowerBBValues.clear();
        m_macdValues.clear(); m_macdSignalValues.clear(); m_rsiValues.clear();
        return;
    }

    // 默认常用周期
    int smaPeriod = 20;
    int emaPeriod = 12; // 常用于短期
    int rsiPeriod = 14;
    int macdFast = 12, macdSlow = 26, macdSignal = 9;
    int bbPeriod = 20; double bbDev = 2.0;

    m_smaValues = calculateSMA(smaPeriod);
    m_emaValues = calculateEMA(emaPeriod);
    m_rsiValues = calculateRSI(rsiPeriod);
    calculateMACD(macdFast, macdSlow, macdSignal, m_macdValues, m_macdSignalValues);
    calculateBollinger(bbPeriod, bbDev, m_upperBBValues, m_lowerBBValues);
}

QVector<double> RealTimeCandlestickChart::calculateSMA(int period) const
{
    int n = m_klineData.size();
    QVector<double> res(n, qQNaN());
    if (n <= 0 || period <= 0) return res;
    double sum = 0;
    for (int i = 0; i < n; ++i) {
        sum += m_klineData[i].close;
        if (i >= period) sum -= m_klineData[i - period].close;
        if (i >= period - 1) res[i] = sum / period;
    }
    return res;
}

QVector<double> RealTimeCandlestickChart::calculateEMA(int period) const
{
    int n = m_klineData.size();
    QVector<double> res(n, qQNaN());
    if (n <= 0 || period <= 0) return res;
    double alpha = 2.0 / (period + 1.0);
    double prev = 0;
    bool hasPrev = false;
    for (int i = 0; i < n; ++i) {
        double price = m_klineData[i].close;
        if (!hasPrev) {
            // 初始值使用简单平均（当数据足够时）
            if (i >= period - 1) {
                double sum = 0;
                for (int j = i - period + 1; j <= i; ++j) sum += m_klineData[j].close;
                prev = sum / period;
                hasPrev = true;
                res[i] = prev;
            }
        } else {
            prev = alpha * (price - prev) + prev;
            res[i] = prev;
        }
    }
    return res;
}

QVector<double> RealTimeCandlestickChart::calculateRSI(int period) const
{
    int n = m_klineData.size();
    QVector<double> res(n, qQNaN());
    if (n <= 0 || period <= 0) return res;
    double gain = 0, loss = 0;
    // 初始平均增益/损失
    for (int i = 1; i <= qMin(n - 1, period); ++i) {
        double diff = m_klineData[i].close - m_klineData[i - 1].close;
        if (diff > 0) gain += diff; else loss -= diff;
    }
    if (n > period) {
        double avgGain = gain / period;
        double avgLoss = loss / period;
        res[period] = (avgLoss == 0) ? 100.0 : (100.0 - (100.0 / (1.0 + avgGain / avgLoss)));
        for (int i = period + 1; i < n; ++i) {
            double diff = m_klineData[i].close - m_klineData[i - 1].close;
            double thisGain = diff > 0 ? diff : 0;
            double thisLoss = diff < 0 ? -diff : 0;
            avgGain = (avgGain * (period - 1) + thisGain) / period;
            avgLoss = (avgLoss * (period - 1) + thisLoss) / period;
            res[i] = (avgLoss == 0) ? 100.0 : (100.0 - (100.0 / (1.0 + avgGain / avgLoss)));
        }
    }
    return res;
}

void RealTimeCandlestickChart::calculateMACD(int fastPeriod, int slowPeriod, int signalPeriod, QVector<double> &macdOut, QVector<double> &signalOut) const
{
    int n = m_klineData.size();
    macdOut.fill(qQNaN(), n);
    signalOut.fill(qQNaN(), n);
    if (n <= 0) return;
    QVector<double> emaFast = calculateEMA(fastPeriod);
    QVector<double> emaSlow = calculateEMA(slowPeriod);
    QVector<double> macd(n, qQNaN());
    for (int i = 0; i < n; ++i) {
        if (!qIsNaN(emaFast[i]) && !qIsNaN(emaSlow[i])) macd[i] = emaFast[i] - emaSlow[i];
    }
    // signal line: EMA of macd
    // 简单实现：用收盘价替代衍生 ema 函数 - 先构造虚拟 KLineData 作为 macd 并调用 calculateEMA
    // 这里直接实现 EMA on macd
    double alpha = 2.0 / (signalPeriod + 1.0);
    double prev = 0; bool hasPrev = false;
    for (int i = 0; i < n; ++i) {
        if (qIsNaN(macd[i])) continue;
        double v = macd[i];
        if (!hasPrev) {
            // find first value to seed
            prev = v; hasPrev = true; signalOut[i] = prev;
        } else {
            prev = alpha * (v - prev) + prev;
            signalOut[i] = prev;
        }
    }
    macdOut = macd;
}

void RealTimeCandlestickChart::calculateBollinger(int period, double devFactor, QVector<double> &upper, QVector<double> &lower) const
{
    int n = m_klineData.size();
    upper.fill(qQNaN(), n);
    lower.fill(qQNaN(), n);
    if (n <= 0 || period <= 0) return;
    for (int i = period - 1; i < n; ++i) {
        double sum = 0;
        for (int j = i - period + 1; j <= i; ++j) sum += m_klineData[j].close;
        double mean = sum / period;
        double sd = 0;
        for (int j = i - period + 1; j <= i; ++j) sd += qPow(m_klineData[j].close - mean, 2);
        sd = qSqrt(sd / period);
        upper[i] = mean + devFactor * sd;
        lower[i] = mean - devFactor * sd;
    }
}

void RealTimeCandlestickChart::refreshIndicatorSeries()
{
    int n = m_klineData.size();
    if (n == 0) return;
    int start = m_startIndex;
    int end = qMin(n - 1, start + m_visibleBars - 1);
    int visibleCount = end - start + 1;

    auto fillSeries = [&](QLineSeries *series, const QVector<double> &values) {
        if (!series) return;
        series->clear();
        if (!series->isVisible()) return;
        for (int i = start; i <= end; ++i) {
            double v = (i < values.size()) ? values[i] : qQNaN();
            if (!qIsNaN(v)) series->append(i - start, v);
        }
    };

    fillSeries(m_smaSeries, m_smaValues);
    fillSeries(m_emaSeries, m_emaValues);
    fillSeries(m_upperBBSeries, m_upperBBValues);
    fillSeries(m_lowerBBSeries, m_lowerBBValues);
    fillSeries(m_macdSeries, m_macdValues);
    fillSeries(m_macdSignalSeries, m_macdSignalValues);
    fillSeries(m_rsiSeries, m_rsiValues);
}

void RealTimeCandlestickChart::updateHoverInfo(int index)
{
    if (index < 0 || index >= m_klineData.size()) return;

    const KLineData &k = m_klineData[index];
    QDateTime dt = QDateTime::fromMSecsSinceEpoch(k.timestamp);
/**
    // 如果图形项未初始化，回退到表格显示（兼容旧逻辑）
    if (!m_infoText || !m_infoBox || !m_vLine || !m_hLine) {
        if (!m_infoTable) return;
        auto setVal = [&](int row, const QString &v) {
            QTableWidgetItem *it = m_infoTable->item(row, 1);
            if (!it) {
                it = new QTableWidgetItem(v);
                it->setFlags(Qt::ItemIsEnabled);
                m_infoTable->setItem(row, 1, it);
            } else {
                it->setText(v);
            }
        };
        setVal(0, dt.toString("yyyy-MM-dd hh:mm"));
        setVal(1, QString::number(k.open, 'f', 8));
        setVal(2, QString::number(k.high, 'f', 8));
        setVal(3, QString::number(k.low, 'f', 8));
        setVal(4, QString::number(k.close, 'f', 8));
        setVal(5, QString::number(k.volume, 'f', 6));
        return;
    }
*/
    // 构建显示文本
    QString info = QString("%1\n开盘价:%2 最高价:%3\n最低价:%4 收盘价:%5\n交易量:%6")
            .arg(dt.toString("yyyy-MM-dd hh:mm"))
            .arg(k.open, 0, 'f', 8)
            .arg(k.high, 0, 'f', 8)
            .arg(k.low, 0, 'f', 8)
            .arg(k.close, 0, 'f', 8)
            .arg(k.volume, 0, 'f', 6);

    m_infoText->setText(info);

    // 计算文本与框大小（增加内边距）
    QRectF textRect = m_infoText->boundingRect();
    QSizeF boxSize(textRect.width() + 8, textRect.height() + 8);

    // 计算可见区域的 scene 坐标
    QRect vp = m_chartView->viewport()->rect();
    QPointF sceneTL = m_chartView->mapToScene(vp.topLeft());
    QPointF sceneBR = m_chartView->mapToScene(vp.bottomRight());

    // 计算 x 的 scene 坐标（根据 index 在可见区的位置）
    int start = m_startIndex;
    int end = qMin(m_klineData.size() - 1, start + m_visibleBars - 1);
    int visibleCount = qMax(1, end - start + 1);
    int posIndex = qBound(0, index - start, visibleCount - 1);
    double xRatio = (visibleCount > 1) ? (posIndex / double(visibleCount - 1)) : 0.5;
    double sceneX = sceneTL.x() + xRatio * (sceneBR.x() - sceneTL.x());

    // 计算 y 的 scene 坐标（使用收盘价映射到当前 axisY）
    double sceneY = (sceneTL.y() + sceneBR.y()) / 2.0;
    if (QValueAxis *axisY = qobject_cast<QValueAxis*>(m_chart->axisY())) {
        double minV = axisY->min();
        double maxV = axisY->max();
        if (maxV > minV) {
            double yRatio = (k.close - minV) / (maxV - minV);
            yRatio = qBound(0.0, yRatio, 1.0);
            sceneY = sceneBR.y() - yRatio * (sceneBR.y() - sceneTL.y());
        }
    }

    // 更新十字线
    m_vLine->setLine(sceneX, sceneTL.y(), sceneX, sceneBR.y());
    m_hLine->setLine(sceneTL.x(), sceneY, sceneBR.x(), sceneY);
    m_vLine->setVisible(true);
    m_hLine->setVisible(true);

    // 放置信息框：优先放在 K 线旁边（靠近蜡烛中间），右侧优先，若超出则放左侧；垂直居中到蜡烛
    QPointF preferred(sceneX + 8, sceneY - boxSize.height() / 2.0);
    // 若超出右边界，改放在左侧
    if (preferred.x() + boxSize.width() > sceneBR.x()) preferred.setX(sceneX - 8 - boxSize.width());
    // 确保不会超出左边界
    if (preferred.x() < sceneTL.x()) preferred.setX(sceneTL.x() + 4);
    // 保证垂直不超出上下边界
    if (preferred.y() + boxSize.height() > sceneBR.y()) preferred.setY(sceneBR.y() - boxSize.height() - 4);
    if (preferred.y() < sceneTL.y()) preferred.setY(sceneTL.y() + 4);

    m_infoBox->setRect(QRectF(preferred, boxSize));
    m_infoBox->setVisible(true);

    m_infoText->setPos(preferred + QPointF(4,4));
    m_infoText->setVisible(true);
}

void RealTimeCandlestickChart::clearHoverInfo()
{
    // 隐藏图表内浮层
    if (m_vLine) m_vLine->setVisible(false);
    if (m_hLine) m_hLine->setVisible(false);
    if (m_infoBox) m_infoBox->setVisible(false);
    if (m_infoText) m_infoText->setVisible(false);
/**
    // 同时清空外部表格内容以保持一致（若存在）
    if (m_infoTable) {
        for (int r = 0; r < m_infoTable->rowCount(); ++r) {
            QTableWidgetItem *it = m_infoTable->item(r, 1);
            if (it) it->setText("-");
        }
    }

*/
}
